package org.feng.navigation.rest.gatewayimpl.youdao;

import lombok.extern.slf4j.Slf4j;
import org.feng.navigation.common.util.GsonUtil;
import org.feng.navigation.common.util.StringUtil;
import org.feng.navigation.domain.rpc.youdao.domainobject.YouDaoTextTranslationRequest;
import org.feng.navigation.domain.rpc.youdao.domainobject.YouDaoTextTranslationResponse;
import org.feng.navigation.domain.rpc.youdao.gateway.YouDaoHttpClient;
import org.feng.navigation.rest.config.AppInfoConfig;
import org.feng.navigation.rest.config.HttpUrlConfig;
import org.feng.navigation.rest.config.appinfo.YouDaoAppInfo;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 有道智云-AI开放平台接口实现
 *
 * @version V1.0
 * @author: junzi
 * @date: 2023年01月10日 10时24分
 */
@Slf4j
@Component
public class YouDaoHttpClientImpl implements YouDaoHttpClient {

    @Resource
    private AppInfoConfig appInfoConfig;
    @Resource
    private HttpUrlConfig httpUrlConfig;
    @Resource
    private RestTemplate restTemplate;

    @Override
    public YouDaoTextTranslationResponse executeTextTranslate(YouDaoTextTranslationRequest request) {
        YouDaoAppInfo youDao = appInfoConfig.getYouDao();
        String appKey = youDao.getAppKey();
        String appSecret = youDao.getAppSecret();

        String currentTime = String.valueOf(System.currentTimeMillis() / 1000);
        String salt = StringUtil.uuid();
        String sign = makeSign(request.getQ(), appKey, appSecret, currentTime, salt);
        request.setCurrentTime(currentTime);
        request.setSalt(salt);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("from", request.getFrom());
        body.add("to", request.getTo());
        body.add("signType", request.getSignType());
        body.add("curtime", request.getCurrentTime());
        body.add("appKey", appKey);
        body.add("q", request.getQ());
        body.add("salt", salt);
        body.add("sign", sign);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        YouDaoTextTranslationResponse response;
        try {
            log.info("有道云文本翻译接口 请求入参：{}", request.toJson());
            String responseStr = restTemplate.postForObject(httpUrlConfig.getYouDao(), requestEntity, String.class);
            log.info("有道云文本翻译接口 响应结果：{}", responseStr);
            response = GsonUtil.fromJson(responseStr, request.getResponseClass());
            return response;
        } catch (Exception e) {
            try {
                log.info("有道云文本翻译接口 请求出错：{}", e.getMessage());
                response = request.getResponseClass().getDeclaredConstructor().newInstance();
                response.setErrorCode("-1");
                response.setErrorMessage(e.getMessage());
                return response;
            } catch (InvocationTargetException | InstantiationException | IllegalAccessException |
                     NoSuchMethodException ex) {
                throw new RuntimeException(ex);
            }
        }
    }


    /**
     * 生成加密字段
     */
    private static String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes(StandardCharsets.UTF_8);
        try {
            MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    private static String truncate(String q) {
        if (q == null) {
            return null;
        }
        int len = q.length();
        return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
    }

    private static String makeSign(String itemText, String appKey, String appSecret, String currentTime, String salt) {
        String signStr = appKey + truncate(itemText) + salt + currentTime + appSecret;
        return getDigest(signStr);
    }
}
